/*
  backgrid-typahead-cell
*/
(function (root, factory) {

    if (typeof define === 'function' && define.amd) {
        // AMD
        define(["underscore", "backgrid", "typeahead"], factory);
    } else if (typeof exports === 'object') {
        // CommonJS
        module.exports = factory(require("underscore"), require("backgrid"), require("typeahead"));
    } else {
        // Browser globals
        factory(root._, root.Backgrid, root.typeahead);
    }

}(this, function (_, Backgrid)  {

  "use strict";

  /**
     @class Backgrid.Extension.TypeaheadCellEditor
     @extends Backgrid.CellEditor
   */
  var TypeaheadCellEditor = Backgrid.Extension.TypeaheadCellEditor = Backgrid.InputCellEditor.extend({

    /** @property */
    events: {
        "mousedown": function () {
            this.mouseDown = true;
        },
        "blur": "enterOrExitEditMode",
        "mouseup": function () {
            this.mouseDown = false;
        },
        "change": "saveOrCancel",
        //"keydown": "saveOrCancel"
    },

    /** @property */
    typeaheadOptions: {
    },

    initialize: function () {
      Backgrid.CellEditor.prototype.initialize.apply(this, arguments);
    },

    /**
       Sets the options for `typeahead`. Called by the parent TypeaheadCell during
       edit mode.
     */
    setTypeaheadOptions: function (options) {
      this.typeaheadOptions = _.extend(options || {});
    },

    /**
       @chainable
     */
    render: function () {
      Backgrid.CellEditor.prototype.render.apply(this, arguments);
      $(this.$el[0]).typeahead(this.typeaheadOptions);
      return this;
    },

    /**
       Attach event handlers to the typeahead box and focus it.
    */
    postRender: function (model, column) {
        if (column == null || column.get("name") == this.column.get("name")) {
            this.$el.focus();
        }
        return this;
      //var self = this;
      //if (self.multiple) self.$el.typeahead("container").keydown(self.close);
      //else self.$el.data("typeahead").focusser.keydown(self.close);

      //self.$el.on("typeahead-blur", function (e) {
      //  if (!self.multiple) {
      //    e.type = "blur";
      //    self.close(e);
      //  }
      //  else {
      //    // HACK to get around https://github.com/ivaynberg/typeahead/issues/2011
      //    // typeahead-blur is triggered from blur and is fired repeatibly under
      //    // multiple select. Since blue is fired before everything, but focus
      //    // is set in focus and click, we need to wait for a while so other
      //    // event handlers may have a chance to run.
      //    var id = setTimeout(function () {
      //      clearTimeout(id);
      //      if (!self.$el.typeahead("isFocused")) {
      //        e.type = "blur";
      //        self.close(e);
      //      }
      //    }, 200);
      //  }
      //}).typeahead("focus");
    },

    remove: function () {
      this.$el.typeahead("destroy");
      return Backgrid.CellEditor.prototype.remove.apply(this, arguments);
    },

    /**
     Event handler. Hack to deal with the case where `blur` is fired before
     `change` and `click` on a checkbox.
    */
    enterOrExitEditMode: function (e) {
        if (!this.mouseDown) {
            var model = this.model;
            model.trigger("backgrid:edited", model, this.column, new Backgrid.Command(e));
        }
    },

      /**
         Event handler. Save the value into the model if the event is `change` or
         one of the keyboard navigation key presses. Exit edit mode without saving
         if `escape` was pressed.
      */
    saveOrCancel: function (e) {
        var model = this.model;
        var column = this.column;
        var formatter = this.formatter;
        var command = new Backgrid.Command(e);
        // skip ahead to `change` when space is pressed
        if (command.passThru() && e.type != "change") return true;
        if (command.cancel()) {
            e.stopPropagation();
            model.trigger("backgrid:edited", model, column, command);
        }

        var $el = this.$el;
        if (command.save() || command.moveLeft() || command.moveRight() || command.moveUp() ||
            command.moveDown()) {
            e.preventDefault();
            e.stopPropagation();
            var val = formatter.toRaw($el.val(), model);
            model.set(column.get("name"), val);
            model.trigger("backgrid:edited", model, column, command);
        }
        else if (e.type == "change") {
            var val = formatter.toRaw($el.val(), model);
            model.set(column.get("name"), val);
            $el.focus();
        }
  }

  });

  /**
     TypeaheadCell is a cell class that renders a `typeahead` select box during edit
     mode.

     @class Backgrid.Extension.TypeaheadCell
     @extends Backgrid.Cell
   */
  Backgrid.Extension.TypeaheadCell = Backgrid.Extension['typeahead'] = Backgrid.Cell.extend({

    /** @property */
    className: "typeahead-cell",

    /** @property */
    editor: TypeaheadCellEditor,

    /** @property */
    typeaheadOptions: null,

    /**
       Initializer.

       @param {Object} options
       @param {Backbone.Model} options.model
       @param {Backgrid.Column} options.column
       @param {Object} [options.typeaheadOptions]

       @throws {TypeError} If `optionsValues` is undefined.
     */
    initialize: function (options) {
        this.typeaheadOptions = options.typeaheadOptions || this.typeaheadOptions;

        this.listenTo(this.model, "backgrid:edit", function (model, column, cell, editor) {
            if (column.get("name") == this.column.get("name")) {
                editor.setTypeaheadOptions(this.typeaheadOptions);
            }
        });

        Backgrid.Cell.prototype.initialize.apply(this, arguments);
    }

  });

}));
